package main

import (
	"log"

	"gitee.com/thewalkers/refactoring-code/handler"
	"gitee.com/thewalkers/refactoring-code/logger"
	"gitee.com/thewalkers/refactoring-code/repository"
	"gitee.com/thewalkers/refactoring-code/service"
	"github.com/gin-gonic/gin"
)

// will initialize a handler starting from data sources
// which inject into repository layer
// which inject into service layer
// which inject into handler layer
func inject(d *dataSources) (*gin.Engine, error) {
	log.Println("Injecting data sources")

	/*
	* repository layer
	 */

	employeeRepository := repository.NewEmployeeRepository(d.DB)
	employeeService := service.NewEmployeeService(&service.EMConfig{
		EmployeeRespository: employeeRepository,
	})

	paycheckRepository := repository.NewPayCheckRepository(d.DB)
	paycheckService := service.NewPayCheckService(&service.PAConfig{
		PaycheckRespository: paycheckRepository,
	})

	paymentClassificationRepository := repository.NewPaymentClassificationRepository(d.DB)
	paymentClassificationService := service.NewPaymentClassificationService(&service.PCConfig{
		PaymentClassificationRepository: paymentClassificationRepository,
	})

	paymentMethodRepository := repository.NewPaymentMethodRepository(d.DB)
	paymentMethodService := service.NewPaymentMethodService(&service.PMConfig{
		PaymentMethodRepository: paymentMethodRepository,
	})

	paymentSchduleRepository := repository.NewPaymentSchduleRepository(d.DB)
	paymentSchduleService := service.NewPaymentSchduleService(&service.PSConfig{
		PaymentScheduleRepository: paymentSchduleRepository,
	})

	addEmployeeTransActionRepository := repository.NewAddEmployeeTransactionRepository(d.DB)
	addEmployeeTransActionService := service.NewAddEmployeeTransactionService(&service.AEConfig{
		AddEmployeeTransActionRepository: addEmployeeTransActionRepository,
	})

	addCommissionedEmployeeTransactionRepository := repository.NewAddCommissionedEmployeeTransactionRepository(d.DB)
	addCommissionedEmployeeTransactionService := service.NewAddCommissionedEmployeeTransactionService(&service.ACConfig{
		AddCommissionedEmployeeTransactionRepository: addCommissionedEmployeeTransactionRepository,
	})

	addHourlyEmployeeTransactionRepository := repository.NewAddHourlyEmployeeTransactionRepository(d.DB)
	addHourlyEmployeeTransactionService := service.NewAddHourlyEmployeeTransactionService(&service.AHConfig{
		AddHourlyEmployeeTransactionRepository: addHourlyEmployeeTransactionRepository,
	})

	addSalaryEmployeeTransactionRepository := repository.NewAddSalaryEmployeeTransactionRepository(d.DB)
	addSalaryEmployeeTransactionService := service.NewAddSalaryEmployeeTransactionService(&service.ASConfig{
		AddSalaryEmployeeTransactionRepository: addSalaryEmployeeTransactionRepository,
	})

	commissionedClassificationRepository := repository.NewCommissionedClassificationRepository(d.DB)
	commissionedClassificationService := service.NewCommissionedClassificationService(&service.CCConfig{
		PaymentClassificationRepository:      paymentClassificationRepository,
		CommissionedClassificationRepository: commissionedClassificationRepository,
	})

	hourlyClassificationRepository := repository.NewHourlyClassificationRepository(d.DB)
	hourlyClassificationService := service.NewHourlyClassificationService(&service.HCConfig{
		PaymentClassificationRepository:   paymentClassificationRepository,
		ChangeHourlyTransactionRepository: hourlyClassificationRepository,
	})

	salariedClassificationRepository := repository.NewSalariedClassificationRepository(d.DB)
	salariedClassificationService := service.NewSalariedClassificationService(&service.SCConfig{
		PaymentClassificationRepository:     paymentClassificationRepository,
		ChangeSalariedTransactionRepository: salariedClassificationRepository,
	})

	// Payment Method Repository
	paymentMethodRepostory := repository.NewPaymentMethodRepository(d.DB)

	mailMethodRepository := repository.NewMailMethodRepository(d.DB)
	mailMethodService := service.NewMailMethodService(&service.MMConfig{
		PaymentMethodRepository: paymentMethodRepostory,
		MailMethodRepository:    mailMethodRepository,
	})

	directMethodRepository := repository.NewDirectMethodRepository(d.DB)
	directMethodService := service.NewDirectMethodService(&service.DMConfig{
		PaymentMethodRepository: paymentMethodRepostory,
		DirectMethodRepository:  directMethodRepository,
	})

	router := gin.New()
	router.Use(logger.GinLogger(), logger.GinRecovery(true))

	handler.NewHandler(&handler.Config{
		R:                             router,
		EmployeeService:               employeeService,
		PaycheckService:               paycheckService,
		PaymentClassificationService:  paymentClassificationService,
		PaymentMethodService:          paymentMethodService,
		PaymentScheduleService:        paymentSchduleService,
		AddEmployeeTransActionService: addEmployeeTransActionService,
		AddCommissionedEmployeeTransactionService: addCommissionedEmployeeTransactionService,
		AddHourlyEmployeeTransactionService:       addHourlyEmployeeTransactionService,
		AddSalaryEmployeeTransactionService:       addSalaryEmployeeTransactionService,
		CommissionedClassificationService:         commissionedClassificationService,
		ChangeHourlyTransactionService:            hourlyClassificationService,
		ChangeSalariedTransactionService:          salariedClassificationService,
		MailMethodService:                         mailMethodService,
		DirectMethodService:                       directMethodService,
	})

	return router, nil
}
